package org.dromara.quickswing.ui.swing;

import org.jdesktop.core.animation.timing.Animator;
import org.jdesktop.core.animation.timing.TimingTarget;
import org.jdesktop.core.animation.timing.TimingTargetAdapter;
import org.jdesktop.swing.animation.timing.sources.SwingTimerTimingSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class AnimateButton extends JButton {

    private static final Logger log = LoggerFactory.getLogger(AnimateButton.class);

    public Color getEffectColor() {
        return effectColor;
    }

    public void setEffectColor(Color effectColor) {
        this.effectColor = effectColor;
    }

    public AnimateButton setArcWidth(int arcWidth) {
        this.arcWidth = arcWidth;
        return this;
    }

    public AnimateButton setArcHeight(int arcHeight) {
        this.arcHeight = arcHeight;
        return this;
    }

    private int arcWidth = 0;
    private int arcHeight = 0;

    private Animator animator;
    private int targetSize;
    private float animateSize;
    private Point pressedPoint;
    private float alpha;
    private Color effectColor = new Color(255, 255, 255);

    public AnimateButton() {
        setContentAreaFilled(false);
        setBorder(new EmptyBorder(5, 0, 5, 0));
        setBackground(Color.WHITE);
        setCursor(new Cursor(Cursor.HAND_CURSOR));
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent me) {
                if (animator != null) {
                    animator.stop();
                }

                targetSize = Math.max(getWidth(), getHeight()) * 2;
                animateSize = 0;
                pressedPoint = me.getPoint();
                alpha = 0.5f;

                SwingTimerTimingSource animationTimer = new SwingTimerTimingSource();
                animationTimer.init();
                animationTimer.addPostTickListener((source, nanoTime) -> SwingUtilities.invokeLater(AnimateButton.this::repaint));

                TimingTarget target = new TimingTargetAdapter() {
                    @Override
                    public void timingEvent(Animator source, double fraction) {
                        if (fraction > 0.5f) {
                            alpha = (float) (1 - fraction);
                        }
                        animateSize = (float) (fraction * targetSize);
                        SwingUtilities.invokeLater(AnimateButton.this::repaint);
                    }
                };

                animator = new Animator.Builder(animationTimer)
                        .setDebugName("700")
                        .setDuration(700, MILLISECONDS)
                        .setDisposeTimingSource(true)
                        .addTargets(target)
                        .build();
                animator.start();
            }
        });

    }

    @Override
    protected void paintComponent(Graphics graphics) {
        int width = getWidth();
        int height = getHeight();
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(getBackground());
        g2.fillRoundRect(0, 0, width, height, arcWidth, arcHeight);
        if (pressedPoint != null) {
            g2.setColor(effectColor);
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            g2.fillOval((int) (pressedPoint.x - animateSize / 2), (int) (pressedPoint.y - animateSize / 2), (int) animateSize, (int) animateSize);
        }
        g2.dispose();
        graphics.drawImage(img, 0, 0, null);
        super.paintComponent(graphics);
    }
}
